package com.zzj.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzj.base.Result;
import com.zzj.entity.Notice;
import com.zzj.handle.WebSocket;
import com.zzj.model.dto.notice.NoticeCreateDTO;
import com.zzj.model.dto.notice.NoticeUpdateDTO;
import com.zzj.model.dto.QueryListDTO;
import com.zzj.service.INoticeService;
import com.zzj.service.RedisService;
import com.zzj.utils.JWTUtil;
import com.zzj.utils.QueryUtil;
import com.zzj.utils.RedisUtil;
import jakarta.annotation.Resource;
import org.apache.http.HttpHeaders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 公告 前端控制器
 * </p>
 *
 * @author zzj
 * @since 2023-02-27
 */
@RestController
@RequestMapping("/notice")
public class NoticeController {

    @Resource
    private INoticeService noticeService;
    @Resource
    private WebSocket webSocket;

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedisService redisService;

    @Transactional
    @PostMapping("list")
    public Result list(@RequestBody @Validated QueryListDTO in) {

        QueryWrapper<Notice> queryWrapper = QueryUtil.paramsWrapper(in.getAndParams(), in.getOrParams(), in.getOrderParams());
        Page<Notice> noticePage = new Page<>(in.getPageNo(), in.getPageSize());
        IPage<Notice> noticeIPage = noticeService.getBaseMapper().selectPage(noticePage, queryWrapper);
        return Result.success(noticeIPage);
    }

    @Transactional
    @PostMapping("create")
    public Result create(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token,
                         @RequestBody @Validated NoticeCreateDTO in) {
        String creatorUsername = JWTUtil.getUsername(token);
        Notice notice = new Notice();
        notice.setCreatorUsername(creatorUsername);
        notice.setTitle(in.getTitle());
        notice.setContent(in.getContent());
        notice.setReceiveUsername(in.getReceiveUsername());
        noticeService.save(notice);
        return Result.success("创建成功");
    }

    @Transactional
    @PostMapping("update")
    public Result update(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token,
                         @RequestBody @Validated NoticeUpdateDTO in) {
        String creatorUsername = JWTUtil.getUsername(token);
        Notice notice = new Notice();
        notice.setId(in.getId());
        notice.setCreatorUsername(creatorUsername);
        notice.setTitle(in.getTitle());
        notice.setContent(in.getContent());
        noticeService.updateById(notice);
        return Result.success("修改成功");
    }

    @Transactional
    @PostMapping("publish")
    public Result publish(@RequestParam String id) throws IOException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        boolean update = noticeService.lambdaUpdate()
                .eq(Notice::getId, id)
                .set(Notice::getStatus, 1)
                .set(Notice::getUpdateTime, format.format(new Date()))
                .update();
        if (!update) {
            return Result.error("发布失败");
        }

        Notice one = noticeService.find(Integer.parseInt(id));
        if (one.getReceiveUsername() != null && !Objects.equals(one.getReceiveUsername(), "")) {
            webSocket.sendNotice(one.getReceiveUsername());
        } else {
            webSocket.sendAllNotice();
        }
        return Result.success("发布成功");
    }

    @PostMapping("revoke")
    public Result revoke(@RequestParam String id) throws IOException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        boolean update = noticeService.lambdaUpdate()
                .eq(Notice::getId, id)
                .set(Notice::getUpdateTime, format.format(new Date()))
                .set(Notice::getStatus, 0)
                .update();
        if (!update) {
            return Result.error("撤销失败");
        }
        Notice one = noticeService.find(Integer.parseInt(id));
        if (one.getReceiveUsername() != null && !Objects.equals(one.getReceiveUsername(), "")) {
            webSocket.sendCancelNotice(one.getReceiveUsername());
        } else {
            webSocket.sendCancelAllNotice();
        }
        return Result.success("撤销成功");
    }


    /**
     * 系统通告是否已读
     * 0未读 1已读
     *
     * @param token
     * @param in
     * @return
     */
    @PostMapping("queryList")
    public Result queryList(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token,
                            @RequestBody @Validated QueryListDTO in) {
        String username = JWTUtil.getUsername(token);
        LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
        Page<Notice> noticePage = new Page<>(in.getPageNo(), in.getPageSize());
        queryWrapper
                .eq(Notice::getStatus, 1)
                .and(i -> {
                    i.eq(Notice::getReceiveUsername, "")
                            .or()
                            .eq(Notice::getReceiveUsername, username);
                })
                .orderByDesc(Notice::getUpdateTime);
        IPage<Notice> noticeIPage = noticeService.getBaseMapper().selectPage(noticePage, queryWrapper);
        List<Notice> notices = noticeIPage.getRecords();

        String noticeReadId = redisService.getNoticeReadId(username);
        if (noticeReadId != null && !noticeReadId.equals("")) {
            String[] split = noticeReadId.split(",");
            List<String> reads = Arrays.asList(split);
            List<Notice> list = notices.stream()
                    .map(notice -> reads.stream()
                            .filter(str -> notice.getId() == Integer.parseInt(str))
                            .findFirst()
                            .map(str -> {
                                notice.setIsRead(1);
                                return notice;
                            }).orElse(notice)).collect(Collectors.toList());
            return Result.success(list);
        } else {
            return Result.success(notices);
        }
    }

    @PostMapping("queryById")
    public Result queryById(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token,
                            @RequestParam int id) {
        String username = JWTUtil.getUsername(token);
        String noticeReadId = redisService.getNoticeReadId(username);
        if(noticeReadId==null){
            noticeReadId="";
        }
        String[] split = noticeReadId.split(",");
        List<String> reads = Arrays.asList(split);
        if (!reads.contains(String.valueOf(id))) {
            noticeReadId += id + ",";
            redisService.setNoticeReadId(username, noticeReadId);
        }
        Notice one = noticeService.find(id);
        return Result.success(one);
    }


    /**
     * 获取公告未读数量
     *
     * @param token
     * @return
     */
    @PostMapping("getNoticeNoReadNum")
    public Result getCommentNoReadNum(@RequestHeader(value = "Authorization") String token) {
        String username = JWTUtil.getUsername(token);
        int noticeNoReadNum = noticeService.getNoticeNoReadNum(username);
        return Result.success(noticeNoReadNum);
    }
}
